package dwetl.runner;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import dwetl.model.DimColumn;
import dwetl.model.DimMdfTable;
import dwetl.model.DimTable;
import dwetl.model.FactColumn;
import dwetl.model.FactTable;
import dwetl.transformer.DimMdfTalbeTransformer;
import dwetl.transformer.FactTableTransformer;
import dwetl.util.ConfigUtil;

@Service
@Scope("prototype")
public final class EtlBuilder {
    private static final Logger logger = LoggerFactory.getLogger(EtlBuilder.class);
    
    @Autowired
    private DimMdfTalbeTransformer dimMdfTalbeTransformer;
    @Autowired
    private FactTableTransformer factTableTransformer;

    private DimMdfTable dimMdfTable;
    private FactTable factTable;

    public static EtlBuilder getInstance(String clsPathFileName){
        try {
            JSONObject json = ConfigUtil.loadJsonFromClassPath(clsPathFileName);
            return new EtlBuilder(json);
        }catch(Exception e){
            throw new RuntimeException(e);
        }
    }

    public EtlBuilder(){
    }
    
    private EtlBuilder(JSONObject jo){//初始化读入一个json配置
        this.init(jo);
    }

    public void init(String clsPathFileName){
        try {
            JSONObject json = ConfigUtil.loadJsonFromClassPath(clsPathFileName);
            init(json);
        }catch(Exception e){
            throw new RuntimeException(e);
        }
    }

    public void init(JSONObject jo){
        this.dimMdfTable=null;
        this.factTable=null;
        List<DimTable> dtbls=parseDim(jo);

        DimMdfTable dmtbl=parseMdfDim(jo);
        if(dmtbl!=null) {
            dmtbl.setDimTables(dtbls);
            this.dimMdfTable=dmtbl;
            logger.info(dmtbl.toString());
        }
        FactTable ftbl=parseFact(jo);
        if(ftbl!=null) {
            ftbl.setDimTables(dtbls);
            this.factTable=ftbl;
            logger.info(ftbl.toString());
        }
    }

    // 配置文件事实表信息转换成FactTable对象存储
    private FactTable parseFact(JSONObject jsonObject) {
        JSONObject jo = jsonObject.getJSONObject("fact_table");

        if(jo!=null) {
            FactTable factTable = new FactTable();
            factTable.setProjectName(jsonObject.getString("project_name"));
            Boolean enable_dim_cache=jsonObject.getBoolean("enable_dim_cache");
            if(enable_dim_cache==false){
                factTable.setEnable_dim_cache(enable_dim_cache);
                this.factTableTransformer.enableDimCache(false);
            }else{
                this.factTableTransformer.enableDimCache(true);
            }
            factTable.setTable_name(jo.getString("table_name"));

            JSONArray ja = jo.getJSONArray("etl_columns");
            for (int j = 0; j < ja.size(); j++) {
                FactColumn factColumn = new FactColumn();

                JSONObject jo2 = ja.getJSONObject(j);
                factColumn.setSrc_col(jo2.getString("src_col"));
                factColumn.setCol(jo2.getString("col"));
                factColumn.setIs_ref_id(jo2.getString("is_ref_id"));
                factColumn.setDim_id_from(jo2.getString("dim_id_from"));
                factColumn.setIs_auto_id(jo2.getBoolean("is_auto_id"));
                factColumn.setTransform_func(jo2.getString("transform_func"));

                factTable.getEtl_columns().add(factColumn);
            }

            return factTable;
        }
        return null;
    }

    // 将配置文件中维表信息转换成DimMdfTable对象存储
    private DimMdfTable parseMdfDim(JSONObject jsonObject) {
        JSONObject jo = jsonObject.getJSONObject("dim_mdf_table");
        if(jo!=null){
            DimMdfTable dimTable = new DimMdfTable();
            dimTable.setProjectName(jsonObject.getString("project_name"));
            Boolean enable_dim_cache=jsonObject.getBoolean("enable_dim_cache");
            if(enable_dim_cache==false){
                dimTable.setEnable_dim_cache(enable_dim_cache);
                this.dimMdfTalbeTransformer.enableDimCache(false);
            }else{
                this.dimMdfTalbeTransformer.enableDimCache(true);
            }
            dimTable.setTable_name(jo.getString("table_name"));
            JSONArray ja = jo.getJSONArray("etl_columns");
            for (int j = 0; j < ja.size(); j++) {
                JSONObject jo2 = ja.getJSONObject(j);
                DimColumn dimColumn = parseDimColumn(jo2);
                dimTable.getEtl_columns().add(dimColumn);
            }

            putUncheckProp(jo,dimTable);
            return dimTable;
        }else{
            return null;
        }
    }

    private DimColumn parseDimColumn(JSONObject jo2){
        DimColumn dimColumn = new DimColumn();
        dimColumn.setSrc_col(jo2.getString("src_col"));
        dimColumn.setCol(jo2.getString("col"));
        dimColumn.setIs_auto_id(jo2.getBoolean("is_auto_id"));
        dimColumn.setIs_ref_id(jo2.getString("is_ref_id"));
        dimColumn.setDim_id_from(jo2.getString("dim_id_from"));
        dimColumn.setTransform_func(jo2.getString("transform_func"));
        return dimColumn;
    }

    private void putUncheckProp(JSONObject jo,DimTable dt){
        JSONObject ucjo=jo.getJSONObject("unique_check");
        SortedSet<String> ukcols=new TreeSet<String>(ucjo.getJSONArray("unique_key_columns").toJavaList(String.class));
        dt.setUnique_key_columns(ukcols);

        List<String> ucols= ucjo.getJSONArray("uncheck_columns").toJavaList(String.class);
        dt.setUncheck_columns(ucols);

        dt.setUnique_key_date_column(ucjo.getString("unique_key_date_column"));
        dt.setIf_exists_skip(ucjo.getBoolean("if_exists_skip"));
    }

    // 将配置文件中维表信息转换成DimTable对象存储
    private List<DimTable> parseDim(JSONObject jsonObject) {
        List<DimTable> list = new ArrayList<DimTable>();

        JSONArray jsonArray = jsonObject.getJSONArray("dim_tables");

        for (int i = 0;jsonArray!=null && i < jsonArray.size(); i++) {
            DimTable dimTable = new DimTable();

            JSONObject jo = jsonArray.getJSONObject(i);
            dimTable.setTable_name(jo.getString("table_name"));
            dimTable.setTable_alias(jo.getString("table_alias"));

            JSONArray ja = jo.getJSONArray("etl_columns");
            for (int j = 0; j < ja.size(); j++) {
                JSONObject jo2 = ja.getJSONObject(j);
                DimColumn dimColumn =parseDimColumn(jo2);
                dimTable.getEtl_columns().add(dimColumn);
            }

            putUncheckProp(jo,dimTable);
            list.add(dimTable);
        }
        return list;
    }

    public Object transform(Map<String,Object> rowMap){
        if(rowMap==null || rowMap.isEmpty()){
            throw new RuntimeException("空数据不做处理");
        }
        if(this.factTable!=null){
            return this.factTableTransformer.doTransform(this.factTable,rowMap);
        }else if(this.dimMdfTable!=null){
            return this.dimMdfTalbeTransformer.doTransform(dimMdfTable,rowMap);
        }
        return null;
    }

    public FactTable getFactCfg(){
        return this.factTable;
    }

    public DimMdfTable getDimMdfCfg(){
        return this.dimMdfTable;
    }
}
